/*
    镜头光晕
    作者：CN.Graphi
*/
Shader "Hidden/CNGraphi/GPostProcess/Lensflare"
{
    SubShader
    {
        Tags { "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline" }
        Cull Off ZWrite Off

        Pass
        {
            HLSLPROGRAM
            #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RealtimeLights.hlsl"

            #include "./Common/GPostProcessFunction.hlsl"
            #include "../Core/Color.hlsl"
            #include "../Core/Lights.hlsl"
            #include "../Core/UV.hlsl"
            #include "../Core/Cam.hlsl"
            

            // /////////////////////////////////////////////////////////
            // 参数

            float _Intensity; // 强度
            float _FocalLength; // 焦距
            float _FocalScaleFactor; // 焦距的缩放因子
            float _StartOffset; // 起始偏移量
            float2 _Center = float2(0.5, 0.5); // 中心位置 
            float _Range = 0.65; //[0-1] // 范围
            float _FadeoutPow = 0.25; // min 0 // 衰减指数

            // 结束
            // /////////////////////////////////////////////////////////



            // 计算当前uv到中心位置的距离
            // centerBase   : 中心位置
            // texcoord     : 当前uv
            // xoffset      : 斜率的x分量
            // yoffset      : 斜率的y分量
            // multi        : 斜率倍数
            float CalculateDist(float2 centerBase, float2 texcoord, float xoffset, float yoffset, float multi = 1.0)
            {
                float multiValue = multi + _StartOffset;
                float2 _Center = float2( centerBase.x + xoffset * multiValue, centerBase.y + yoffset * multiValue ) * 2.0 - 1.0;
                float dist = abs( distance( texcoord , _Center ) );
                return dist;
            }


            // 绘制圆
            // centerBase   : 中心基础位置
            // texcoord     : 屏幕UV坐标
            // radians      : 光圈半径
            // clr          : 颜色
            // xoffset      : 斜率的x分量
            // yoffset      : 斜率的y分量
            // multi        : 斜率倍数
            float4 DrawCircle(float2 centerBase, float2 texcoord, float radians, float4 clr, float xoffset, float yoffset, float multi = 1.0)
            {
                float dist = CalculateDist(centerBase, texcoord, xoffset, yoffset, multi);
                return lerp( 0, clr, 1 - step(radians, dist) );
            }


            // 绘制径向圆（未与 DrawCircle 函数合并，是为了减少函数参数以及函数内部的逻辑判断）
            // centerBase   : 中心基础位置
            // texcoord     : 屏幕UV坐标
            // radians      : 光圈半径
            // dir          : 方向（1：外散径向、0：内撒径向）
            // p            : 插值器指数
            // clr          : 颜色
            // xoffset      : 斜率的x分量
            // yoffset      : 斜率的y分量
            // multi        : 斜率倍数
            float4 DrawRadialCircle(float2 centerBase, float2 texcoord, float radians, float dir, float p, float4 clr, float xoffset, float yoffset, float multi = 1.0)
            {
                float dist = CalculateDist(centerBase, texcoord, xoffset, yoffset, multi);
                float factor = smoothstep(0, radians, dist);
                if(dir == 1)
                {
                    return lerp(clr, 0, pow(factor, p));
                }
                else
                {
                    factor *= 1.0 - step(radians, dist);
                    return lerp(0, clr, pow(factor, p));
                }
            }


            // 绘制光圈
            // centerBase   : 中心基础位置
            // texcoord     : 屏幕UV坐标
            // radians      : 光圈半径
            // p            : 插值器指数
            // clr          : 颜色
            // xoffset      : 斜率的x分量
            // yoffset      : 斜率的y分量
            // multi        : 斜率倍数
            float4 DrawAperture(float2 centerBase, float2 texcoord, float radians, float p, float4 clr, float xoffset, float yoffset, float multi = 1.0)
            {
                float dist = CalculateDist(centerBase, texcoord, xoffset, yoffset, multi);
                float factor = smoothstep(0, radians, dist);
                float4 clr1 = lerp(clr, 0, pow(factor, p));
                float4 clr2 = lerp(0, clr, pow(factor, p));
                return clr1 * clr2;
            }


            // 35毫米焦距
            float4 Draw35(float2 _Center, float2 uv, float xoffset, float yoffset)
            {
                float4 c = DrawRadialCircle( _Center, uv, 0.45, 1, 90, float4(0.4445532, 0.6981132, 0.4998754, 1) * 0.15, xoffset, yoffset );
                c += DrawAperture( _Center, uv, 0.37, 40, float4(0.4811321, 0.2927643, 0.2927643, 1), xoffset, yoffset );
                c += DrawRadialCircle( _Center, uv, 0.05, 1, 0.04, float4(0.7294118, 0.9529412, 0.8509804, 1) *3, xoffset, yoffset, 0.88 );
                c += DrawRadialCircle( _Center, uv, 0.05, 1, 0.3, float4(0.8962264, 0.5030705, 0.5333133, 1) *0.5, xoffset, yoffset, 0.95 );
                c += DrawRadialCircle( _Center, uv, 0.15, 1, 0.5, float4(0.7921569, 0.7058824, 0.2235294, 1) *0.3, xoffset, yoffset, 1.05 );
                c += DrawCircle( _Center, uv, 0.15, float4(0.4696984, 0.4385457, 0.6886792,1) * 0.05, xoffset, yoffset, 0.5 );
                c += DrawRadialCircle( _Center, uv, 0.1, 1, 2, float4(0.3589356, 0.6070603, 0.6981132, 1) *0.3, xoffset, yoffset, -0.2 );
                c += DrawRadialCircle( _Center, uv, 0.045, 1, 2, float4(0.3589356, 0.6070603, 0.6981132, 1) *0.3, xoffset, yoffset, -0.11 );
                return c;
            }
            // 105毫米焦距
            float4 Draw105(float2 _Center, float2 uv, float xoffset, float yoffset)
            {
                float4 c = DrawCircle( _Center, uv, 0.5, float4(0.9410601, 0.990566, 0.0513973, 1.0) * 0.015, xoffset, yoffset, 0.45 ); 
                c += DrawCircle( _Center, uv, 0.3, float4(0.9410601, 0.990566, 0.0513973, 1.0) * 0.015, xoffset, yoffset, 0.45 ); 
                c += DrawRadialCircle( _Center, uv, 0.03, 1, 0.2, float4(0.8490566, 0.672195, 0.244304, 1.0), xoffset, yoffset, 0.1 );
                c += DrawRadialCircle( _Center, uv, 0.03, 0, 1, float4(0, 0.7672267, 1, 1.0) * 0.08, xoffset, yoffset, 0.25 );
                c += DrawRadialCircle( _Center, uv, 0.05, 1, 0.05, float4(0, 0.7672267, 1, 1.0) *3, xoffset, yoffset, 0.26 );
                c += DrawCircle( _Center, uv, 0.08, float4(0, 1, 0.3359518, 1.0) * 0.04, xoffset, yoffset, 0.5 );
                c += DrawCircle( _Center, uv, 0.08, float4(0, 1, 0.3359518, 1.0) * 0.04, xoffset, yoffset, 0.55 );
                c += DrawRadialCircle( _Center, uv, 0.03, 1, 0.05, float4(0.9410601, 0.990566, 0.0513973, 1.0) *2, xoffset, yoffset, 0.54 );
                c += DrawCircle( _Center, uv, 0.12, float4(0.5262988, 0.05098037, 0.3483447, 1.0) * 0.04, xoffset, yoffset, 0.75 );
                c += DrawCircle( _Center, uv, 0.2, float4(0.379774, 0.7169812, 0.3483447, 1.0) * 0.1, xoffset, yoffset, 0.98 );
                c += DrawCircle( _Center, uv, 0.14, float4(0.6698113, 0.5149964, 0.5149964, 1.0) * 0.12, xoffset, yoffset, 0.98 );
                c += DrawRadialCircle( _Center, uv, 0.08, 0, 2, float4(0.7333333, 0.8666667, 0.8427669, 1.0) * 0.15, xoffset, yoffset, 1.03 );
                c += DrawCircle( _Center, uv, 0.04, float4(0.9410601, 0.990566, 0.0513973, 1.0) * 0.15, xoffset, yoffset, 0.74 );
                c += DrawRadialCircle( _Center, uv, 0.05, 1, 0.02, float4(1, 1, 1, 1.0) *6, xoffset, yoffset, 0.75 );
                c += DrawCircle( _Center, uv, 0.04, float4(0, 0.7672267, 1, 1.0) * 0.15, xoffset, yoffset, 0.83 );
                c += DrawRadialCircle( _Center, uv, 0.04, 1, 0.05, float4(1, 1, 1, 1.0) *3, xoffset, yoffset, 0.83 );
                c += DrawCircle( _Center, uv, 0.03, float4(0, 1, 0.2251561, 1.0) * 0.15, xoffset, yoffset, -0.2 );
                c += DrawRadialCircle( _Center, uv, 0.04, 1, 0.05, float4(0.9410601, 0.990566, 0.0513973, 1.0) *3, xoffset, yoffset, -0.215 );
                return c;
            }
            // 50-300毫米焦距
            float4 Draw50_300(float2 _Center, float2 uv, float xoffset, float yoffset)
            {
                float4 c = DrawAperture( _Center, uv, 0.4, 170, float4(0.4125387, 0.261926, 0.509434, 1.0) * 0.7, xoffset, yoffset );
                c += DrawAperture( _Center, uv, 0.42, 170, float4(0.379774, 0.7169812, 0.3483447, 1.0) * 0.7, xoffset, yoffset );
                c += DrawAperture( _Center, uv, 0.44, 170, float4(0.8679245, 0.8183481, 0.2661089, 1.0) * 0.7, xoffset, yoffset );
                c += DrawRadialCircle( _Center, uv, 0.2, 0, 2, float4(0.8490566, 0.672195, 0.244304, 1.0) * 0.08, xoffset, yoffset, 0.84 );
                c += DrawCircle( _Center, uv, 0.11, float4(0.8490566, 0.672195, 0.244304, 1.0) * 0.08, xoffset, yoffset, 0.82 );
                c += DrawCircle( _Center, uv, 0.06, float4(0.8490566, 0.672195, 0.244304, 1.0) * 0.08, xoffset, yoffset, 0.87 );
                c += DrawRadialCircle( _Center, uv, 0.25, 0, 2, float4(0.379774, 0.7169812, 0.3483447, 1.0) * 0.08, xoffset, yoffset, 1.03 );
                c += DrawAperture( _Center, uv, 0.25, 170, float4(0.8679245, 0.8183481, 0.2661089, 1.0) * 0.5, xoffset, yoffset, 1.03 );
                c += DrawCircle( _Center, uv, 0.08, float4(0.379774, 0.7169812, 0.3483447, 1.0) * 0.2, xoffset, yoffset, 0.93 );
                c += DrawRadialCircle( _Center, uv, 0.04, 1, 0.5, float4(0.2431372, 0.4574338, 0.8509804, 1.0), xoffset, yoffset, 0.93 );
                c += DrawRadialCircle( _Center, uv, 0.04, 1, 0.04, float4(0.379774, 0.7169812, 0.3483447, 1.0) *3 , xoffset, yoffset, 0.64 );
                c += DrawRadialCircle( _Center, uv, 0.04, 1, 0.1, float4(0.379774, 0.7169812, 0.3483447, 1.0) *4 , xoffset, yoffset, 0.74 );
                c += DrawCircle( _Center, uv, 0.2, float4(0.2431372, 0.3668588, 0.8509804, 1.0) * 0.05, xoffset, yoffset, 0.4);
                c += DrawCircle( _Center, uv, 0.1, float4(0.2431372, 0.3668588, 0.8509804, 1.0) * 0.06, xoffset, yoffset, 0.44);
                c += DrawCircle( _Center, uv, 0.08, float4(0.8509804, 0.6801669, 0.2431372, 1.0) * 0.07, xoffset, yoffset, 0.52);
                c += DrawAperture( _Center, uv, 0.23, 60, float4(1, 0.1181408, 0, 1.0) * 0.6, xoffset, yoffset, 0.22 );
                c += DrawRadialCircle( _Center, uv, 0.1, 0, 10, float4(0.8490566, 0.672195, 0.244304, 1.0) * 0.08 , xoffset, yoffset, 0.135 );
                return c;
            }



            // 自定义片元着色函数
            half4 Frag (Varyings input) : SV_Target
            {
                // 后处理计算需要的常用参数
                float deviceDepth;
                PositionInputs posInputs;
                float3 V;
                float3 normalizeV;
                GetComputeInformations(input, deviceDepth, posInputs, V, normalizeV);
                UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);

                // 采样背景色
                float4 clr = SampleBlitTex( input.texcoord );

                // 摄像机当前朝向
                float3 cameraDirection = GetCurrentCamDir();
                // 当前主光源方向
                Light light = GetMainLight();
                float3 lightDirection = light.direction;
                // 摄像机方向与主光源方向的夹角（用于镜头光晕的衰减程度）
                float VdotL = dot( normalize(cameraDirection) , normalize(lightDirection) );
                VdotL = smoothstep(_Range, 1, VdotL);
                VdotL = pow(VdotL, _FadeoutPow);

                // 计算斜率
                float2 slope = CalculateMainlightDirToScreen( lightDirection ) * _FocalScaleFactor;
                float xoffset = slope.x;
                float yoffset = slope.y;

                // 绘制
                float2 uv = UVAspect( input.texcoord );
                float4 flare = 0;
                UNITY_BRANCH
                if(_FocalLength == 0){
                    flare =  Draw35(_Center, uv, xoffset, yoffset);
                }
                else if(_FocalLength == 1){
                    flare =  Draw105(_Center, uv, xoffset, yoffset);
                }
                else if(_FocalLength == 2){
                    flare =  Draw50_300(_Center, uv, xoffset, yoffset);
                }
                flare *= _Intensity * VdotL;


                // 返回最终颜色
                float4 final = clr + flare;
                return final;
            }


            // 着色程序
            #pragma vertex Vert
            #pragma fragment Frag
            ENDHLSL
        }
    }

    FallBack Off
}